package com.frogs.ucenter.v1.service.impl;

import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import javax.annotation.Resource;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.frogs.framework.util.PageList;
import com.frogs.framework.util.StringUtil;
import com.frogs.framework.util.date.DateUtil;
import com.frogs.system.util.InsuranceCodeStatusEnum;
import com.frogs.system.util.InsuranceRecordStatusEnum;
import com.frogs.system.web.api.request.Request;
import com.frogs.system.web.api.response.Response;
import com.frogs.system.web.api.response.Response.ApiResultEnum;
import com.frogs.system.web.exception.ServiceOperationException;
import com.frogs.ucenter.dao.InsuranceCodeDao;
import com.frogs.ucenter.dao.InsuranceInfoDao;
import com.frogs.ucenter.dao.InsuranceRecordDao;
import com.frogs.ucenter.dao.InsuranceUserInfoDao;
import com.frogs.ucenter.entity.InsuranceCode;
import com.frogs.ucenter.entity.InsuranceInfo;
import com.frogs.ucenter.entity.InsuranceRecord;
import com.frogs.ucenter.entity.InsuranceRecordExt;
import com.frogs.ucenter.entity.InsuranceRecordJoinInsuranceInfoExt;
import com.frogs.ucenter.entity.InsuranceRecordJoinInsuranceUserExt;
import com.frogs.ucenter.entity.InsuranceUserInfo;
import com.frogs.ucenter.entity.PartnerInsuranceRecord;
import com.frogs.ucenter.v1.request.InsuranceCodeAddRequest;
import com.frogs.ucenter.v1.request.InsuranceInfoListRequest;
import com.frogs.ucenter.v1.request.InsuranceRecordAddRequest;
import com.frogs.ucenter.v1.request.InsuranceRecordDeleteRequest;
import com.frogs.ucenter.v1.request.InsuranceRecordDetailRequest;
import com.frogs.ucenter.v1.request.InsuranceRecordListRequest;
import com.frogs.ucenter.v1.response.AddResponse;
import com.frogs.ucenter.v1.response.DefaultResponse;
import com.frogs.ucenter.v1.response.PageListResponse;
import com.frogs.ucenter.v1.response.ShowResponse;
import com.frogs.ucenter.v1.service.InsuranceService;
import com.frogs.ucenter.v1.service.insurance.center.PartnerInsuranceCompanyCenter;
import com.frogs.ucenter.v1.util.ApiConstants;

/**
 * @author wushubin
 *
 */
@Transactional(propagation=Propagation.REQUIRED, rollbackFor=Exception.class) 
@Service(ApiConstants.VERSION+"insuranceService")
public class InsuranceServiceImpl implements InsuranceService{
	
	private static final Logger log = LoggerFactory.getLogger(InsuranceServiceImpl.class);
	
	@Resource
    private InsuranceCodeDao insuranceCodeDao;
	
	@Resource
    private InsuranceInfoDao insuranceInfoDao;
	
	@Resource
    private InsuranceRecordDao insuranceRecordDao;
	
	@Resource
    private InsuranceUserInfoDao insuranceUserInfoDao;
	
	@Resource(name=ApiConstants.VERSION + "partnerInsuranceCompanyCenter")
    private PartnerInsuranceCompanyCenter partnerInsuranceCompanyCenter;
	
	@Override
	public Response insertCode(Request request) throws Exception{
		AddResponse<InsuranceCode> response = new AddResponse<InsuranceCode>();
        
    	try {
    		String code = StringUtil.getRandomString(4) + new Date().getTime() + StringUtil.getRandomString(4);
    		InsuranceCodeAddRequest addRequest = (InsuranceCodeAddRequest)request;
    		InsuranceCode insuranceCode = new InsuranceCode();
    		insuranceCode.setCode(code);
    		insuranceCode.setOrderSn(addRequest.getOrderSn());
    		insuranceCode.setUserId(addRequest.getUserId());
    		insuranceCode.setInsuranceId(addRequest.getInsuranceId());
    		insuranceCodeDao.insert(insuranceCode);
    		
	        response.setInfo(insuranceCode);
	        response.setTip("激活码创建成功");
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}
	
	/**
	 * 注：本地保存的      投保人 受益人 被保人的id都是以insuranceUserInfo表的id为主
	 *    同步给合作方的投保人 受益人 被保人的id都是以对方的用户id为主
	 */
	@Override
	public Response insertInsuranceRecord(Request request) throws Exception {
		AddResponse<InsuranceRecordJoinInsuranceInfoExt> response = new AddResponse<InsuranceRecordJoinInsuranceInfoExt>();
		InsuranceRecordAddRequest addRequest = (InsuranceRecordAddRequest)request;
		
		try {
			log.info("func[insertInsuranceRecord] request[{}] ", new Object[] {JSON.toJSONString(request)});
	        
			//1.验证激活码
			InsuranceCode insuranceCode = this.verifyCode(addRequest);
			
			//2.查询保险详情
			InsuranceInfo insuranceInfo = insuranceInfoDao.selectById(insuranceCode.getInsuranceId());
			
			//3.创建好药师投保人信息
			InsuranceUserInfo insuranceUserInfo = this.insertUserInfo(addRequest,insuranceInfo);
			
			//4.创建本地保单信息
			InsuranceRecordJoinInsuranceInfoExt record = this.insertInsuranceRecord(insuranceInfo,insuranceUserInfo);
			
			//5.同步投保人信息到合作方保险公司,同时创建保单
			PartnerInsuranceRecord partnerInsuranceRecord = partnerInsuranceCompanyCenter.add(addRequest, insuranceInfo,record);

			if(partnerInsuranceRecord.getCode() == ApiResultEnum.SUCCESS.getId()){
				//6.修改本地保单信息
				record.setInsuranceName(insuranceInfo.getName());
				
				this.updateInsuranceRecord(partnerInsuranceRecord,(InsuranceRecord)record);

				//7.激活码设置为已使用
				this.updateInsuranceCode(insuranceCode, addRequest.getUserId());
				
				response.setInfo(record);
				response.setTip("投保成功");
			}
			else{
				response.setInfo(null);
				response.setCode(ApiResultEnum.FAIL.getId());;
				response.setTip(partnerInsuranceRecord.getTip());
			}
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}
	
	private void updateInsuranceCode(InsuranceCode insuranceCode ,int userId){
		insuranceCode.setStatus(InsuranceCodeStatusEnum.RUN_OUT.getId());
		if(insuranceCode.getUserId() == 0)
			insuranceCode.setUserId(userId);
		insuranceCodeDao.update(insuranceCode);
	}
	
	/**
	 * 创建保单
	 * @param addRequest
	 * @param insuranceInfo
	 * @return
	 */
	private InsuranceRecordJoinInsuranceInfoExt insertInsuranceRecord(InsuranceInfo insuranceInfo ,InsuranceUserInfo insuranceUserInfo){
		InsuranceRecordJoinInsuranceInfoExt object = new InsuranceRecordJoinInsuranceInfoExt();
		object.setBeneficiaryUserId(insuranceUserInfo.getId());
		object.setChannelOrderNo(insuranceInfo.getCompanyId()+"-"+new Date().getTime());
		object.setInsuranceId(insuranceInfo.getId());
		object.setInsuredUserId(insuranceUserInfo.getUserId());
		object.setPolicyHolderUserId(insuranceUserInfo.getId());
		object.setUserId(insuranceUserInfo.getUserId());
		insuranceRecordDao.insert((InsuranceRecord)object);
		return object;
	}
	
	/**
	 * 修改保单
	 * @param addRequest
	 * @param insuranceInfo
	 * @return
	 */
	private void updateInsuranceRecord(PartnerInsuranceRecord partnerInsuranceRecord,InsuranceRecord object){
		object.setEndDate(partnerInsuranceRecord.getPolicyEndDate());
		object.setPolicyId(partnerInsuranceRecord.getPolicyId());
		object.setPolicyNo(partnerInsuranceRecord.getPolicyNo());
		object.setPremium(partnerInsuranceRecord.getPremium());
		object.setStartDate(partnerInsuranceRecord.getPolicyBeginDate());
		object.setStatus(InsuranceRecordStatusEnum.NORMAL.getId());
		insuranceRecordDao.update(object);
	}
	
	/**
	 * 创建投保人信息
	 */
	private InsuranceUserInfo insertUserInfo(InsuranceRecordAddRequest addRequest,InsuranceInfo insuranceInfo){
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("eqUserId", addRequest.getUserId());
		params.put("eqIdentityCard",addRequest.getIdentityCard());
		PageList<InsuranceUserInfo> userList = insuranceUserInfoDao.selectByMap(params, 1, 1, false);
		if(userList.size() == 0 ){
			InsuranceUserInfo object = new InsuranceUserInfo();
			object.setChannelId(insuranceInfo.getChannelId());
			object.setChannelUserNo(insuranceInfo.getCompanyId() + "-" + DateUtil.getCurrentUnixTimeSecond());
			object.setEmail(addRequest.getEmail());
			object.setIdentityCard(addRequest.getIdentityCard());
			object.setName(addRequest.getName());
			object.setPhone(addRequest.getPhone());
			object.setSex(addRequest.getSex());
			object.setUserId(addRequest.getUserId());
			insuranceUserInfoDao.insert(object);
			return object;
		}
		return userList.get(0);
	}
	
	/**
	 * 验证激活码
	 * @param addRequest
	 */
	private InsuranceCode verifyCode(InsuranceRecordAddRequest addRequest) throws Exception {
		
		Map<String,Object> params = new HashMap<String,Object>();
		params.put("eqCode", addRequest.getCode());
		params.put("eqStatus", InsuranceCodeStatusEnum.NORMAL.getId());
		PageList<InsuranceCode> codeList = insuranceCodeDao.selectByMap(params, 1, 1, false);
		log.info("func[verifyCode] codeList[{}] ", new Object[] {JSON.toJSONString(codeList)});
        
		if(codeList.size() == 0)
			throw new ServiceOperationException("激活码失效"); 
		
		return codeList.get(0);
	}
	
	
	@Override
	public Response deleteInsuranceRecord(Request request) throws Exception {
		// TODO Auto-generated method stub
		DefaultResponse response = new DefaultResponse();
        
		try {
			InsuranceRecordDeleteRequest deleteRequest = (InsuranceRecordDeleteRequest)request;
			//查询保险详情和保单详情
			InsuranceRecord record = insuranceRecordDao.selectById(deleteRequest.getRecordId());
			if(record.getUserId().intValue() != deleteRequest.getUserId())
				throw new ServiceOperationException("请求处理失败：保单所属人有误！");
			
			InsuranceInfo info = insuranceInfoDao.selectById(record.getInsuranceId());
			//1.同步退保信息到合作方
			partnerInsuranceCompanyCenter.quit(info, record);
			//2.修改本地保单信息
			record.setStatus(InsuranceRecordStatusEnum.QUIT.getId());
			record.setEffectTime(new Date());
			insuranceRecordDao.update(record);
			
	        response.setTip("退保成功");
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}

	/**
	 * 获取保险信息列表
	 */
	@Override
	public Response getInsuranceInfoList(Request request) throws Exception {

		PageListResponse<InsuranceInfo> response = new PageListResponse<InsuranceInfo>();
        
		try {
			InsuranceInfoListRequest listRequest = (InsuranceInfoListRequest)request;
			
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("inIdList", listRequest.getIds().split(","));
			PageList<InsuranceInfo> list = insuranceInfoDao.selectByMap(params, 1,1000,false);
    		
	        response.setList(list);
	        response.setTip("保险列表查询成功");
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}	
	
	
	/**
	 * 查询用户保单列表
	 */
	@Override
	public Response getInsuranceRecordList(Request request) throws Exception{
		PageListResponse<InsuranceRecordJoinInsuranceInfoExt> response = new PageListResponse<InsuranceRecordJoinInsuranceInfoExt>();
        
		try {
			InsuranceRecordListRequest listRequest = (InsuranceRecordListRequest)request;
			
			Map<String,Object> params = new HashMap<String,Object>();
			params.put("eqUserId",listRequest.getUserId());
			PageList<InsuranceRecordJoinInsuranceInfoExt> list = insuranceRecordDao.selectJoinByMap(params,listRequest.getPageNum(),listRequest.getNumPerPage(),listRequest.isDoCount());
    		
	        response.setList(list);
	        response.setTip("保单列表查询成功");
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}

	@Override
	public Response getInsuranceRecordDetail(Request request) throws Exception {
		ShowResponse<InsuranceRecordExt> response = new ShowResponse<InsuranceRecordExt>();
        
		try {
			InsuranceRecordDetailRequest detailRequest = (InsuranceRecordDetailRequest)request;
			//查询保险详情和保单详情
			InsuranceRecordJoinInsuranceUserExt record = insuranceRecordDao.selectInsuranceRecordJoinInsuranceUserById(detailRequest.getRecordId());
			if(record.getUserId().intValue() != detailRequest.getUserId())
				throw new ServiceOperationException("请求处理失败：保单所属人有误！");
			
			InsuranceInfo info = insuranceInfoDao.selectById(record.getInsuranceId());
			
			InsuranceRecordExt ext = new InsuranceRecordExt();
			ext.setInfo(info);
			ext.setRecord(record);
			
			response.setInfo(ext);
			response.setTip("保单信息查询成功");
	    } catch (Exception e) {
	    	log.error("func[{}] request[{}] exception[{}] desc[fail]",
					new Object[] { this.getClass().getName() +"."+Thread.currentThread().getStackTrace()[1].getMethodName(),
						request,Arrays.deepToString(e.getStackTrace()) });
			throw new ServiceOperationException("请求处理失败：" + e.getMessage());
		}
	    return response;
	}
}

